/*
** map.c for pud in mrcellophane/libpud
** 
** Made by solomon hykes
** Login   <torgau@gmail.com>
** 
** Started on  Tue May 17 20:08:38 2005 solomon hykes
** Last update Thu Jul 14 16:30:17 2005 solomon hykes
*/

#include <signal.h>
#include <fcntl.h>
#include "pud.h"
#include <sys/mman.h>
#include <stdio.h>

static pud_process	*proc = NULL;

void	bye(int sig)
{
  if (proc != NULL)
    pud_detach(proc);
  printf("Terminated by signal %d\n", sig);
  exit(0);
}

int	get_perms(char *str)
{
  int	perms = 0;

  if (strlen(str) != 3)
    return (-1);
  if (str[0] == 'r')
    perms |= PROT_READ;
  else if (str[0] != '-')
    return (-1);

  if (str[1] == 'w')
    perms |= PROT_WRITE;
  else if (str[1] != '-')
    return (-1);

  if (str[2] == 'x')
    perms |= PROT_EXEC;
  else if (str[2] != '-')
    return (-1);
  return (perms);
}

void	die_usage()
{
  fputs("Usage: psalloc pid size permissions\n\tPermissions: \"rwx\", \"-wx\", \"r-x\", etc.\n", stderr);
  exit(1);
}

int	main(int argc, char **argv)
{
  int		perms;
  int		pid;
  unsigned long	size;
  int		worker;

  if (argc < 4)
    die_usage();
  pid = atoi(argv[1]);
  size = atol(argv[2]);
  perms = get_perms(argv[3]);
  if (perms == -1)
    die_usage();
  signal(SIGINT, bye);
  signal(SIGSEGV, bye);
  do_psalloc(pid, size, perms);
  return (0);
}

int	do_psalloc(int pid, unsigned long size, int perms)
{
  pud_event	*event;
  u_long	data;

  proc = pud_attach(pid);
  if (proc == NULL)
    {
      perror("pud_attach");
      exit(1);
    }
  event = pud_next_event(proc);
  if (event == NULL)
    {
      perror("pud_next_event");
      exit(1);
    }
  data = pud_mem_alloc(proc, size, perms, MAP_PRIVATE|MAP_ANON);
  printf("%p\n", data);
  pud_detach(proc);
}
